﻿#pragma once
#include "AppDelegate.h"
#include <stdlib.h>
#include <fstream>
#include "SceneFallingSingle.h"
#include "SceneMusicSelect.h"

#define random_r RandomHelper::random_real


USING_NS_CC;

Scene* SceneFallingSingle::createScene()
{
	auto scene = Scene::create();
	auto layer = SceneFallingSingle::create();
	layer->setAnchorPoint(Point(0.5, 0.5));
	scene->addChild(layer);
	return scene;
}

bool SceneFallingSingle::init()
{

	if (!Layer::init())
	{
		return false;
	}

	//string wndtitle = "Playing:[";
	//wndtitle += (pNotemgr->type == NoteManager::FILETYPE::FILE_BMS) ? "BMS" : "OSU MANIA";
	//wndtitle += "]" + pNotemgr->metaData.artist + " - " + pNotemgr->metaData.title + "[" + pNotemgr->metaData.version + "]";
	char* ctitlein = new char[1024];
	memset(ctitlein, 0, 1024);
	string keys;
	if (pNotemgr->type == NoteManager::FILETYPE::FILE_OSU) keys = (strtool::int2str(pNotemgr->trackCount) + "K").c_str();
	else keys = pNotemgr->trackCount < 9 ? "SP" : "DP";
	sprintf_s(ctitlein, 1024, "Playing:[%s]%s - %s[%s %s]",
		(pNotemgr->type == NoteManager::FILETYPE::FILE_OSU) ? "OSU MANIA" : "BMS",
			  (pNotemgr->metaData.artistU).size() > 0 ? pNotemgr->metaData.artistU.c_str() : pNotemgr->metaData.artist.c_str(),
			  (pNotemgr->metaData.titleU).size() > 0 ? pNotemgr->metaData.titleU.c_str() : pNotemgr->metaData.title.c_str(),
			  keys.c_str(),
			  pNotemgr->metaData.version.c_str());
	//auto pctitle = cwndtitle;
	UI::setWndTItle(strtool::Utf82Unicode(ctitlein));

	createBGLayer();
	createBGImage(pNotemgr->bgFile);

	pGameController = new ControllerFallingMode(pNotemgr->mapfilepath, pNotemgr->hispeed, pNotemgr->type);
	createPlayerPanel(pGameController->getTrackCount());
	createHud();
	pGameController->setSceneObject(this->getChildByName("layerHUD"), this->getChildByName("panelFrame"));


	//Create debug class
	debug = new Debug();

	createFadeInMask();

	//Audio System operation
	pAudioSystem->stopBGM();

	auto keyListener = EventListenerKeyboard::create();
	keyListener->onKeyPressed = CC_CALLBACK_2(SceneFallingSingle::onKeyPressed, this);
	keyListener->onKeyReleased = CC_CALLBACK_2(SceneFallingSingle::onKeyReleased, this);
	_eventDispatcher->addEventListenerWithSceneGraphPriority(keyListener, this);

	string teststr = "Preview version.\n";
	teststr += "ESC: Back to music select.\n";
	teststr += "TAB: Toggle auto play.\n";
	teststr += "F1/F2: Hi-Speed -/+ 0.25 .\n\n";
	teststr += "NORMAL Style:\n";
	teststr += "4 Tracks - D F J K\n";
	teststr += "5 Tracks - D F SPACE J K\n";
	teststr += "6 Tracks - S D F J K L\n";
	teststr += "7 Tracks - S D F SPACE J K L\n";
	teststr += "8 Tracks - A S D F J K L ;\n\n";
	teststr += "BM Style:\n";
	teststr += "4 Tracks - LSHIFT Z S X\n";
	teststr += "5 Tracks - Z S X D C\n";
	teststr += "6 Tracks - LSHIFT Z S X D C\n";
	teststr += "7 Tracks - Z S X D C F V\n";
	teststr += "8 Tracks - LSHIFT Z S X D C F V";
	auto testlabel = Label::createWithTTF(teststr, FONTA, 28);
	UI::setNodeAnch(testlabel, ANCH_TR);
	testlabel->enableOutline(Color4B::BLACK, 2);
	testlabel->setPosition(frameSize.width, frameSize.height);
	addChild(testlabel, 65535);

	scheduleUpdate();
	return true;
}

void SceneFallingSingle::createBGLayer()
{
	auto layerBG = LayerColor::create(Color4B::WHITE);
	layerBG->setName("bgLayer");
	this->addChild(layerBG);
}

void SceneFallingSingle::createHud()
{
	auto layerHud = LayerColor::create(pUI->themeColorB(0));
	layerHud->setName("layerHUD");
	this->addChild(layerHud);
}

void SceneFallingSingle::createPlayerPanel(int trackCount)
{
	Size panelSize = Size(frameSize.width / 5 + 20 * trackCount, frameSize.height);
	//float trackWidth = panelSize.width / trackCount;
	//auto layerPanelFrame = LayerColor::create(TEXTCOLORBA(0), panelSize.width, panelSize.height);
	//layerPanelFrame->setPosition((frameSize.width - panelSize.width) / 2, 0);
	auto layerPanelFrame = UIFallingModePanel::create(panelSize, trackCount);
	layerPanelFrame->setPosition(0, 0);
	layerPanelFrame->setName("panelFrame");
	this->addChild(layerPanelFrame);
	//auto frameNode = DrawNode::create();
	//layerPanelFrame->addChild(frameNode);
	//frameNode->drawLine(Point(0, 0), Point(0, panelSize.height), TEXTCOLORFA(225));
	//frameNode->drawLine(Point(panelSize.width, 0), Point(panelSize.width, panelSize.height), TEXTCOLORFA(225));
	//frameNode->drawSolidRect(Point(0, 0), Point(panelSize.width, frameSize.height / 8), TEXTCOLORFA(225));

	//Rect clipRect = Rect(1, frameSize.height / 8, panelSize.width - 2, panelSize.height);
	//auto clipNode = ClippingRectangleNode::create(clipRect);
	//clipNode->setName("panelClip");
	//layerPanelFrame->addChild(clipNode);
	//auto layerGrad = LayerGradient::create(Color4B(0, 0, 0, 160), Color4B(0, 0, 0, 255));
	//clipNode->addChild(layerGrad);
	//auto layerNoteField = LayerColor::create(Color4B(0, 0, 0, 0), panelSize.width, panelSize.height * 7 / 8);
	//UI::setNodeAnch(layerNoteField, ANCH_BL);
	//layerNoteField->setPosition(Point(1, frameSize.height / 8));
	//layerNoteField->setName("panelNoteField");
	//clipNode->addChild(layerNoteField);

	//for (int i = 0; i < trackCount; i++)
	//{
	//	auto key = LayerColor::create(THEMECOLORBA(150), trackWidth - 4, frameSize.height / 8 - 2);
	//	key->setPositionX(trackWidth*i + 2);
	//	char name[5];
	//	sprintf_s(name, 5, "key%d", i);
	//	key->setName(name);
	//	layerPanelFrame->addChild(key);
	//	auto trackLight = Sprite::create("image/GamePlay/FallingTrackLight.png");
	//	UI::setNodeAnch(trackLight, ANCH_MB);
	//	trackLight->setOpacity(180);
	//	trackLight->setPosition(Point(trackWidth*(i + 0.5), frameSize.height / 8));
	//	trackLight->setScale(trackWidth / trackLight->getContentSize().width, 0);
	//	sprintf_s(name, 5, "tkl%d", i);
	//	trackLight->setName(name);
	//	layerPanelFrame->addChild(trackLight);
	//}

}

void SceneFallingSingle::createBGImage(string imgPath)
{
	Sprite* bgImage;
	if (imgPath.empty()) bgImage = Sprite::create();
	else bgImage = Sprite::create(imgPath);
	auto bgSize = bgImage->getContentSize();
	float bgAspectRatio = bgSize.width / bgSize.height;
	float visAspectRatio = frameSize.width / frameSize.height;
	if (bgAspectRatio <= visAspectRatio) bgImage->setScale(frameSize.width / bgSize.width);
	else bgImage->setScale(frameSize.height / bgSize.height);
	bgImage->setPosition(Point(frameSize.width / 2, frameSize.height / 2));
	this->getChildByName("bgLayer")->addChild(bgImage);
}

void SceneFallingSingle::createFadeInMask()
{
	auto layerFadeInMask = LayerColor::create(Color4B::BLACK);
	this->addChild(layerFadeInMask);
	layerFadeInMask->runAction(
		Sequence::create(
			FadeTo::create(0.5, 0),
			RemoveSelf::create(),
			NULL
		)
	);
}

void SceneFallingSingle::backToMusicSelect()
{
	unscheduleUpdate();
	pGameController->exit = true;
	pAudioSystem->stopAllSound();
	auto layerSceneSwitchEffect = LayerColor::create(Color4B::BLACK);
	layerSceneSwitchEffect->setOpacity(0);
	this->addChild(layerSceneSwitchEffect, 65535);
	layerSceneSwitchEffect->runAction(
		Sequence::create(
			FadeTo::create(0.2f, 255),
			CallFunc::create([&]
	{
		pAudioSystem->stopBGM();
		Director* director = Director::getInstance();
		if (pSceneMusicSelect != nullptr)
		{
			//pSceneMusicSelect->release();
		}
		pSceneMusicSelect = SceneMusicSelect::createScene();
		director->replaceScene(pSceneMusicSelect);
	}),
			NULL
		)
	);
}



void SceneFallingSingle::update(float dt)
{
	pGameController->updateController(true);
	bool isbgmplaying;
	pAudioSystem->curbgm.pChl->isPlaying(&isbgmplaying);
	bool isAllObjectPlayed;
	switch (pNotemgr->type)
	{
		case 1:
			if (!isbgmplaying && pGameController->bgmStarted) backToMusicSelect();
			break;

		case 2:
			isAllObjectPlayed = pNotemgr->chlBgm.size() == 0;
			for (int i = 0; i < pNotemgr->trackCount && isAllObjectPlayed; i++)
				isAllObjectPlayed = isAllObjectPlayed && (pNotemgr->trackNotes[i].size() == 0);
			if (isAllObjectPlayed) endCount += dt;
			if (endCount > 5) backToMusicSelect();
			break;

		default:
			break;
	}
	//debugMsg();
}

void SceneFallingSingle::onKeyPressed(EventKeyboard::KeyCode keycode, Event * e)
{
	//pGameController->checkNormalInput(keycode, true);
	//if (keycode == CCKEYCODE::KEY_TAB) pGameController->isAutoPlay = !pGameController->isAutoPlay;
	switch (keycode)
	{
		case CCKEYCODE::KEY_TAB:
			if (pGameController->isAutoPlay)
			{
				pGameController->isAutoPlay = false;
				auto lb = getChildByName("autoplay");
				if (lb != nullptr) lb->removeFromParentAndCleanup(true);
			}
			else
			{
				pGameController->isAutoPlay = true;
				auto lb = Label::createWithTTF("AUTO PLAY", FONTA, 64);
				lb->setOpacity(128);
				lb->setName("autoplay");
				UI::setNodeAnch(lb, ANCH_TL);
				lb->setPosition(0, frameSize.height);
				addChild(lb, 65535);
			}
			break;
		case CCKEYCODE::KEY_ESCAPE:
			if (pGameController->curTime > 1) backToMusicSelect();
			break;
		case CCKEYCODE::KEY_F1:
			pGameController->changeSpeed = -0.25f;
			break;
		case CCKEYCODE::KEY_F2:
			pGameController->changeSpeed = 0.25f;
			break;
		default:
			break;
	}
}

void SceneFallingSingle::onKeyReleased(EventKeyboard::KeyCode keycode, Event * e)
{
	//pGameController->checkNormalInput(keycode, false);
}

void SceneFallingSingle::debugMsg()
{
	debug->deltaTime += Director::getInstance()->getDeltaTime();
	if (debug->deltaTime >= 0)
	{
		debug->deltaTime = 0;

		//PBYTE lpks=new BYTE[256];
		//auto res = GetKeyboardState(lpks);
		//char vkchar = '\0';
		//if (res)
		//{
		//	for (UINT i = 0; i < 256; i++)
		//	{
		//		if (lpks[i]>1)
		//		{
		//			vkchar = MapVirtualKeyA(i, MAPVK_VK_TO_CHAR);
		//		}
		//	}
		//}

		auto bgl = this->getChildByName("bgLayer");
		char* msg = new char[256];
		unsigned int bgmTime = pAudioSystem->getBgmPosition();
		string msgformat = "Delta Time:%.5f*%5f\r\n";
		msgformat += "Top time:%.5f\r\nCur time:%.5f\r\nBgm time:%d\r\n";
		msgformat += "Offset per Buffer:%+2.5f\r\nOffset predict:%+2.5f\r\n";
		msgformat += "Audio Buffer Count:%d\r\n";
		msgformat += "Total Frames:%d\r\n";
		//msgformat += "Key Scan(%d):%c\r\n";
		sprintf(msg,
				msgformat.c_str(),
				pGameController->deltaTime,
				pGameController->deltaTimeMod,
				pGameController->topTime,
				pGameController->curTime,
				bgmTime,
				pGameController->avOffset,
				pGameController->avOffsetPerFrame,
				pGameController->audioBufferCount,
				pGameController->totalFrames//,
				//res, vkchar
		);
		debug->showMsg(bgl, msg);
	}
}
